package org.dfl.core.model;

import org.dfl.messages.Messages;
import org.dfl.plugin.DflPlugin;

import java.util.Collection;

import org.dfl.core.data.History;
import org.dfl.core.data.Token;
import org.dfl.core.data.connectors.CollectionTypeConnector;
import org.dfl.core.data.connectors.SimpleTypeConnector;
import org.dfl.core.data.connectors.TypeConnector;
import org.dfl.core.model.transitions.Transition;
import org.jdom.Element;


/**
 * output edge from a transition
 * @author Piotr Wlodarczyk
 *
 */
public class TOutputEdge extends Edge {

	@SuppressWarnings("unchecked")
	public void setToken(Token token) {
		Object data = token.getData();
		
		// przepuszczamy dane tylko jesli pasuja :)
		if( data == null ||
			(isNeededEmpty() && !((Collection)data).isEmpty()) ||
			(isNeededNotempty() && ((Collection)data).isEmpty()) ||
			(isNeededFalse() && ((Boolean)data).booleanValue()==true) ||
			(isNeededTrue() && ((Boolean)data).booleanValue()==false)){
			return;		
		}
		
		// dla kolekcji i gwiazdki rozbic outputData!! zakladamy, ze typ danych jest sformatowany, czyli jest kolekcja itd.
		if(isNested()){
			Collection origDataCol = (Collection) data;
			for(Object nextData : origDataCol){
				Token token2 = new Token(nextData, new History(nextData, origDataCol, token.getHistory()));
				token2.setActive(token.isActive());
				synchronized (DflPlugin.class) {
					getPlace().addToken(token2);
				}
			}
		}else{
			synchronized (DflPlugin.class) {
				getPlace().addToken(token);
			}
		}
	}

	@Override
	public void connectAction(Place place, Transition transition) throws Exception {
		// inny konektor typow jesli *
		TypeConnector placeConnector = null;
		if(isNested()){
			placeConnector = new CollectionTypeConnector(place.getTypeContainer(), getTypeContainer());
		}else{
			placeConnector = new SimpleTypeConnector(place.getTypeContainer(),getTypeContainer());
		}
		
		// polacz
		if(place.addInputEdge(this,placeConnector)){
			if(!transition.addOutput(this)){
				disconnect();
				throw new Exception(Messages.TOutputEdge_errorPlaceOutput1+place.getId()+Messages.TOutputEdge_errorPlaceOutput2+transition.getName());
			}
		}else{
			//nie powinno sie zdarzyc!
			throw new Exception(Messages.TOutputEdge_errorPlaceOutput1+place.getId()+Messages.TOutputEdge_errorPlaceOutput2+transition.getName());
		}
	}
	
	@Override
	public void disconnectAction() {
		if(getPlace()!=null) 	getPlace().removeInputEdge(this);
		if(getTransition()!=null) getTransition().removeOutput(this);
	}
	
	@Override
	public String toString(){
		return "edge from transition="+getTransition().getName()+" to place="+getPlace().getId(); //$NON-NLS-1$ //$NON-NLS-2$
	}
	
	@Override
	public Element save() {
		Element elem = super.save();
		elem.setAttribute("target",getPlace().getId()); //$NON-NLS-1$
		elem.setAttribute("source",getTransition().getId()); //$NON-NLS-1$
		return elem;
	}
}
